<?php
/**
* ManyToMany.php
*
* Contains ManyToMany class definition
* @author  John Snook <jsnook@gmail.com>
* @version 2
* @copyright (c) Snook 2004
* @package QuickDataFiles
*/

/**
* ManyToMany
*
* This class subclasses OneToMany to provide a Multi-Multi interface.  It's owned by DataForm.
*<code>
* |-----------------------------|      |------------------------|                                          
* | DataTable->DBTableName      |      | IntermediateTable      |      |---------------------------------|
* |-----------------------------|      |------------------------|      | OneToMany->ForeignTable         |
* | Simple->LocalField          |<-----| IntermediateLocalKey   |      |---------------------------------|
* |-----------------------------|      | IntermediateForeignKey |----->| OneToMany->ForeignKeyField      |
*                                      |------------------------|      | OneToMany->ForeignDataField     |
*                                                                      |---------------------------------|
*</code>
* @author  John Snook <jsnook@gmail.com>
* @version 2
* @copyright (c) Snook 2004
* @example /var/www/corp/IntraDox/Projects.php
* @package QuickData
* @subpackage QuickDataFields
*/
class ManyToMany extends OneToMany
{
	/**
	* The join table name.
	* @access public
	* @var string
	*/
	var $IntermediateTable;
	/**
	* The local key field name to tie to our local table.
	* @access public
	* @var string
	*/
	var $IntermediateLocalKey;
	/**
	* The foreign key field name from our foreign table.
	* @access public
	* @var string
	*/
	var $IntermediateForeignKey;
	/**
	* The character to delimit a view mode list.  Default to comma.
	* @access public
	* @var string
	*/
	var $Delimiter = ", ";

	/**
	* The default help string to show in edit/add mode
	* @access public
	* @var string
	*/
	var $HelpText = "(Ctrl + click to select multiple records)";
	
	/**
	* Create an instance of a ManyToMany 
	* @todo Add option to list columns of text boxes.
	* @param array $Caption Duh.
	* @param string $LocalField The name of the local key field, usually the primary key of the local table.
	* @param string $ForeignTable The foreign table name.
	* @param string $ForeignKeyField The foreign key field name.
	* @param string $ForeignDataField The name of the field that has foreign data that we're going to display.
	* @param string $IntermediateTable The join table name.
	* @param string $IntermediateLocalKey The local key field name to tie to our local table.
	* @param string $IntermediateForeignKey The foreign key field name from our foreign table.
	*/

	var $CanInsert = FALSE;
	var $CanSearch = FALSE;
	var $CanQuery = TRUE;
	var $CanAdd = TRUE;
	var $CanEdit = TRUE;

	// expects $Caption, $LocalField, $ForeignTable, $ForeignKeyField, $ForeignDataField, $IntermediateTable, $IntermediateLocalKey, $IntermediateForeignKey
	function ManyToMany($Properties)
	{
		parent::OneToMany($Properties);
	}
	
	function getLocalKeyValue()
	{
		//First we have to determine what our LocalField key value is.
		$SQL = "SELECT {$this->LocalField} FROM {$this->Parent->Parent->DBTableName} WHERE {$this->Parent->Parent->PrimaryKeyName} = {$this->Parent->PrimaryKeyValue}";
		$DB = $this->Parent->Parent->DB;
		$Query = $DB->CreateQuery($SQL);
		$LocalKey = join($Query->FetchRow(),"");
		$Query->Close();
		return $LocalKey;
	}

	/**
	* Updates the IntermediateTable by 1st deleting all existing records that belong to us and then adding the new ones.
	* @return integer Returns a count of rows affected by this query
	*/
	function Update()
	{
		$LocalKey = $this->getLocalKeyValue();
		
		// Delete any existing selections from the join table
		$SQL = "DELETE FROM {$this->IntermediateTable}  WHERE {$this->IntermediateLocalKey} = {$LocalKey}";
//		$out .= "$SQL<BR>";
		$DB = $this->Parent->Parent->DB;
		$DB->CreateQuery($SQL);
		// Now insert all the new selections
		if(is_array($this->Value))
		{
			foreach($this->Value as $value)
			{
				$SQL = "INSERT INTO {$this->IntermediateTable} ({$this->IntermediateLocalKey}, {$this->IntermediateForeignKey})";
				$SQL .= "VALUES ({$LocalKey}, {$value})";
//				$out .= "$SQL<BR>";
				$DB->CreateQuery($SQL);
			}
			return count($this->Value);
		}
	}

	/**
	* This function is not used in this implementation.
	*/
	function GetSQLReadyValue() //not used
	{
		return NULL;
	}

	/**
	* Renders a ManyToMany control.
	*
	* - QD_MODE_VIEW <br>
	*   This control will render a list of ForeignDataField seperated by $this->Delimeter.  
	* - QD_MODE_EDIT<br>
	*   Displays a multi-select list box, with the items from the join table selected.
	* - QD_MODE_ADD<br>
	*   Displays a multi-select list box, with no items selected.
	*
	* @todo add option to list columns of text boxes
	* @param array $DataRow
	* @param integer $DisplayMode QD_MODE_VIEW, QD_MODE_EDIT, QD_MODE_ADD
	*/
	function Render($DataRow, $DisplayMode = QD_MODE_VIEW)
	{
		//Render the caption
		$out .= "\t<tr>\n\t\t<td class=\"" . $this->Parent->ViewCaptionCssClassName . "\">";
		$out .= $this->Caption;
		if ($this->HelpText != '' && $DisplayMode != QD_MODE_VIEW)
		{
			$out .= "<br />$this->HelpText";
		}
		$out .= "</td>\n";

		// Render the HTML
		$out .= "\t\t<td class=\"";
		$out .= $this->Parent->ViewCssClassName . "\">";
		$DB = $this->Parent->Parent->DB;
		if($DisplayMode != QD_MODE_ADD)
		{
			$this->Value = $DataRow[$this->LocalField];
//			$out .= "\$this->Value = $this->Value<br>";
		}
		else 
		{
			$this->Value = NULL;
		}
		if ($this->CanEdit == FALSE)
		{
			$DisplayMode = QD_MODE_VIEW;
		}
		switch($DisplayMode)
		{
			case QD_MODE_VIEW:
//				$out .= "\$DisplayMode = $DisplayMode, \$this->CanEdit = $this->CanEdit, \$this->CanAdd = $this->CanAdd";
				// Build the view query.
				$SQL = "SELECT {$this->ForeignTable}.{$this->ForeignDataField}";
				$SQL .= " FROM {$this->ForeignTable}, {$this->IntermediateTable}, {$this->Parent->Parent->DBTableName}";
				$SQL .= " WHERE {$this->ForeignTable}.{$this->ForeignKeyField} = {$this->IntermediateTable}.{$this->IntermediateForeignKey}";
				$SQL .= " AND {$this->IntermediateTable}.{$this->IntermediateLocalKey} = {$this->Parent->Parent->DBTableName}.{$this->LocalField} ";
				$SQL .= " AND {$this->Parent->Parent->DBTableName}.{$this->LocalField} = {$this->Value}";
//				$out .= "$SQL<br>";
				// Execute the query
				$Query = $DB->CreateQuery($SQL);
				while($row = $Query->FetchRow())
				{
					$output .= $row[$this->ForeignDataField] . $this->Delimiter;
				}
				$out .= substr($output, 0, strlen($output) - strlen($this->Delimiter));
				break;
			case QD_MODE_EDIT: // first select all records from the join table; these will be our be our selections
				$SQL = "SELECT {$this->IntermediateForeignKey}";
				$SQL .= " FROM {$this->IntermediateTable} ";
				$SQL .= " WHERE {$this->IntermediateLocalKey} = {$this->Value}";
//				$out .= "$SQL<br>";
				// Execute the query
				$Query = $DB->CreateQuery($SQL);
				while($row = $Query->FetchRow())
				{
					$selections[] = $row[$this->IntermediateForeignKey];
				}
				//no break, we want to execute the next branch if in edit mode
			case QD_MODE_ADD && $this->CanAdd:
				// then select all records from the foreign table; this will be our list box
				$SQL = "SELECT {$this->ForeignKeyField}, {$this->ForeignDataField} ";
				$SQL .= " FROM {$this->ForeignTable} ";
				if (!is_null($this->ParentKeyName) && !is_null($this->ParentKeyValue))
				{
					$SQL .= " WHERE {$this->ParentKeyName} = {$this->ParentKeyValue}";
				}
				$SQL .= " ORDER BY {$this->ForeignDataField}";
				 
//				$out .= "$SQL<br>";
				// Execute the query
				$Query = $DB->CreateQuery($SQL);
				$count = $Query->NumRows();
				$boxsize =  ($count > 10) ? 10 : $count;
				if ($count >0)
				{
					$out .= "\t\t<select name=\"{$this->Key}[]\" class=\"{$this->Parent->EditCssClassName}\" size=\"$boxsize\" multiple\">\n";
					while ($resultsRow = $Query->FetchRow())
					{
						$out .= "\t\t\t<option ";
						if (is_array($selections))
						{
							if (in_array($resultsRow[$this->ForeignKeyField], $selections))
							{
								$out .= "selected ";
							}
						}
						$out .= " value=\"" . $resultsRow[$this->ForeignKeyField] . "\">" . $resultsRow[$this->ForeignDataField] . "</option>\n";
					}
					$out .= "\t\t</select>";
				}
				break;
		}
		$Query->Close();
		$out .= "</td>\n\t</tr>\n";
		return $out;
	}
}

?>